home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.10 Oct 94 / Sprocket / Lib / DialogWindow.cp < prev    next >
Encoding:
Text File  |  1994-08-25  |  4.9 KB  |  204 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        DialogWindow.cp
  3.  
  4.     Contains:    Implementation of a base class for Modeless Dialogs
  5.                 
  6.     Written by: Dave Falkenburg
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.     To Do:
  13.  */
  14.  
  15. #include    <Dialogs.h>
  16. #include    <Menus.h>
  17. #include    <Desk.h>
  18. #include    <Traps.h>
  19. #include    <Devices.h>
  20.  
  21. #include    "DialogWindow.h"
  22. #include    "AppLib.h"
  23.  
  24.  
  25. TDialogWindow::TDialogWindow(DialogTemplateID dialogTemplateID)
  26.     {
  27.     fTemplateID = dialogTemplateID;
  28.     this->CreateWindow(kNormalWindow);
  29.     }
  30.  
  31.  
  32. WindowPtr
  33. TDialogWindow::MakeNewWindow(WindowPtr behindWindow)
  34.     {
  35.     return GetNewDialog(fTemplateID,nil,behindWindow);
  36.     }
  37.  
  38.  
  39. ////////////////////////////////////////////////////////////////////////////////////
  40. //
  41. //    EventFilter strategy for Dialog Window
  42. //
  43. //    Because of the need to patch and unpatch FrontWindow when calling IsDialogEvent
  44. //    and DialogSelect, only do these things when a Modless Dialog is the frontmost
  45. //    window. (e.g., it’s event filter is active)
  46. //
  47. //    NOTE: We always pass events through, except when an item has been hit.
  48. //
  49. //    You may be thinking that it is easier to just rewrite the Dialog Manager in
  50. //    this program. You’re probably right.
  51.  
  52. pascal    WindowPtr    FrontWindowPatchForDialogs();
  53.  
  54.  
  55. pascal    WindowPtr
  56. FrontWindowPatchForDialogs()
  57.     {
  58.     return FrontNonFloatingWindow();
  59.     }
  60.  
  61. #define    uppFrontWindowPatchProcInfo (kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(WindowPtr))))
  62.  
  63. UniversalProcPtr FrontWindowPatchUPP
  64. = (UniversalProcPtr) NewRoutineDescriptor((ProcPtr) &FrontWindowPatchForDialogs,uppFrontWindowPatchProcInfo,GetCurrentISA());
  65.  
  66.  
  67. Boolean
  68. TDialogWindow::EventFilter(EventRecord *theEvent)
  69.     {
  70.     UniversalProcPtr    oldFrontWindow = GetToolboxTrapAddress(_FrontWindow);
  71.     DialogPtr            aDialog;
  72.     Boolean                eventHasBeenGobbled = false;
  73.     short                aDialogItem;
  74.     short                oldWindowKind;
  75.     
  76.     //    Don’t snarf keypresses meant for menus
  77.     if ((theEvent->what == keyDown) && (theEvent->modifiers & cmdKey))
  78.         return false;
  79.         
  80.     //    Patch in our version of FrontWindow so that IsDialogEvent will do the right
  81.     //    thing. DialogManager should check both frontmost floating and frontmost
  82.     //    non-floating windows, however we don’t support floating dialogs.
  83.     SetToolboxTrapAddress(FrontWindowPatchUPP,_FrontWindow);
  84.  
  85.     //    Jam the windowKind of our dialog window back to dialogKind so that the
  86.     //    Dialog Manager can recognize our window as a dialog window.
  87.     oldWindowKind = ((WindowPeek) fWindow)->windowKind;
  88.     ((WindowPeek) fWindow)->windowKind = dialogKind;
  89.     
  90.     if (IsDialogEvent(theEvent))
  91.         if (DialogSelect(theEvent,&aDialog,&aDialogItem))
  92.             eventHasBeenGobbled = true;
  93.  
  94.     //    Restore the windowKind
  95.     ((WindowPeek) fWindow)->windowKind = oldWindowKind;
  96.  
  97.     //    Put FrontWindow back the way it really belongs
  98.     SetToolboxTrapAddress((UniversalProcPtr) oldFrontWindow,_FrontWindow);
  99.  
  100.     if (eventHasBeenGobbled)
  101.         {
  102.         ItemHit(aDialogItem);    //    Call user’s method to deal with a hit
  103.         return true;
  104.         }
  105.  
  106.     return(false);
  107.     }
  108.  
  109.  
  110. void
  111. TDialogWindow::Activate(Boolean activating)
  112.     {
  113.     /*    (De)activates are NOT automagically handled because our floating
  114.      *    windows prevent real activate events from ever being generated
  115.      *    for any non-floaters windows.
  116.      *
  117.      *    Our strategy is to fool the dialog manager into thinking that
  118.      *    things are still fine by passing it a fake (de)activate event.
  119.      *
  120.      *    Luckily, we don’t have to patch FrontWindow to make DialogSelect
  121.      *    work for activate and update events.
  122.      */
  123.     
  124.     EventRecord            fakeEvent;
  125.         
  126.     OSEventAvail(0,&fakeEvent);        //    Get an intialized, but otherwise empty event record
  127.     
  128.     fakeEvent.what = activateEvt;
  129.     fakeEvent.message = (unsigned long) fWindow;
  130.     if (activating)
  131.         fakeEvent.modifiers |= activeFlag;
  132.     else
  133.         fakeEvent.modifiers &= ~activeFlag;
  134.  
  135.     //    Pass event on to DialogSelect
  136.     
  137.     DialogPtr    aDialog;
  138.     short        aDialogItem;
  139.     
  140.     (void) DialogSelect(&fakeEvent,&aDialog,&aDialogItem);
  141.     }
  142.     
  143.  
  144. void
  145. TDialogWindow::Draw(void)
  146.     {
  147.     //    Automagically handled by Dialog Manager when we are
  148.     //    the frontmost window, but not at other times because
  149.     //    we only set the windowKind to dialogKind inside our
  150.     //    EventFilter (which is only active when we are frontmost).
  151.     
  152.     UpdateDialog((DialogPtr) fWindow, fWindow->visRgn);
  153.     }
  154.     
  155.     
  156. void
  157. TDialogWindow::Click(EventRecord * /* anEvent */)
  158.     {
  159.     /*    The only time this method is called is to handle a click
  160.      *    when the dialog window isn’t frontmost. All other times,
  161.      *    DialogSelect will do everything for us.
  162.      *
  163.      *    If our dialog contains useritems with the ability to
  164.      *    be the source of a drag we’d need to start drag tracking
  165.      *    in here.
  166.      */
  167.      
  168.     this->Select();
  169.     }
  170.  
  171.     
  172. void
  173. TDialogWindow::DoEditMenu(short item)
  174.     {
  175.     switch (item+accMenu)
  176.         {
  177.         case    accUndo:
  178.             break;
  179.             
  180.         case    accCut:
  181.             DlgCut((DialogPtr) &fWindow); 
  182.             break;
  183.             
  184.         case    accCopy:
  185.             DlgCopy((DialogPtr) &fWindow); 
  186.             break;
  187.             
  188.         case    accPaste:
  189.             DlgPaste((DialogPtr) &fWindow); 
  190.             break;
  191.             
  192.         case    accClear:
  193.             DlgDelete((DialogPtr) &fWindow); 
  194.             break;
  195.         }
  196.     }
  197.  
  198.  
  199. void
  200. TDialogWindow::ItemHit(short /* theItem */)
  201.     {
  202.     /*    Override this function to handle dialog items */
  203.     }
  204.